package com.cup.wx.micro.service.impl;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.entity.StringEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.cup.wx.config.WebChatConfig.WXAccountProperties;
import com.cup.wx.config.WebChatConfig.WXUrlProperties;
import com.cup.wx.micro.bean.WXPayOrder;
import com.cup.wx.micro.service.WXPayService;
import com.cup.wx.micro.util.WebchatUtil;
import com.cup.wx.micro.wxpay.WXPayConstants;
import com.cup.wx.micro.wxpay.WXPayUtil;
import com.cup.wx.micro.wxpay.WXPayConstants.SignType;

@Service
@EnableConfigurationProperties({WXAccountProperties.class,WXUrlProperties.class})
public class WXPayServiceImpl implements WXPayService {
	
	@Autowired
	private WXAccountProperties wxaccount;
	
	@Autowired
	private WXUrlProperties wxurl;
	
	@Autowired
	private RestTemplate testTemplate;
//	
//	private Logger logger = LoggerFactory.getLogger(WXPayServiceImpl.class);
	
	/**
     * 向 Map 中添加 appid、mch_id、nonce_str、sign_type、sign <br>
     * 该函数适用于商户适用于统一下单等接口，不适用于红包、代金券接口
     */
    private Map<String, String> fillRequestData(Map<String, String> reqData) throws Exception {
        reqData.put("appid", wxaccount.getAppid());						// appid
        reqData.put("mch_id", wxaccount.getParter());					// 商户ID
        reqData.put("nonce_str", WXPayUtil.generateNonceStr());			// 随机字符串
        reqData.put("sign_type", WXPayConstants.MD5);					// 加签类型
        reqData.put("sign", WebchatUtil.generateSignature(reqData, wxaccount.getPartenerkey())); // 加签
        return reqData;
    }
	
    /**
	 * 统一下预支付订单
	 */
	@Override
	public Map<String, String> unifiedOrder(WXPayOrder payOrder) throws Exception {
		Map<String, String> reqData = new HashMap<>();
		// 交易类型
		String tradeType = payOrder.getTradeType();
    	// 随机串
    	String nonceStr = WebchatUtil.generateNonceStr();
    	// 设置业务参数
    	BigDecimal totalfee = new BigDecimal(payOrder.getTotalfee()).multiply(new BigDecimal("100"));
    	reqData.put("body", payOrder.getDescribe());						// 商品描述
    	reqData.put("out_trade_no", payOrder.getOrderId());					// 商户订单号
    	reqData.put("device_info", payOrder.getDeviceInfo());				// 设备号
    	reqData.put("fee_type", "CNY");										// 标价币种
    	reqData.put("total_fee", String.valueOf(totalfee.intValue()));		// 订单总金额，单位为分
    	reqData.put("spbill_create_ip", payOrder.getIpaddress());			// 终端IP
    	reqData.put("trade_type", tradeType);  								// 支付方式：此处指定为小程序支付 未来可根据前端传入
    	reqData.put("attach", payOrder.getAttach());						// 附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用。 member_id
        reqData.put("notify_url", wxurl.getNotifyurl());					// 支付回调地址
        
        // 向微信发送请求
        HttpHeaders requestHeaders = new HttpHeaders();
		requestHeaders.add("Content-Type", "text/xml");
		requestHeaders.add("User-Agent", WebchatUtil.USER_AGENT + " ");
		StringEntity postEntity = new StringEntity(WebchatUtil.mapToXml(this.fillRequestData(reqData)), "UTF-8");
		HttpEntity<StringEntity> requestEntity = new HttpEntity<StringEntity>(postEntity, requestHeaders);
		ResponseEntity<String> httpEntity = testTemplate.exchange(wxurl.getPaydomain() + wxurl.getUnifiedorder(), 
				HttpMethod.POST, requestEntity, String.class);
		
		String respXml = httpEntity.getBody();
		
//        String respXml = HttpUtil.request(wxurl.getPaydomain() + wxurl.getUnifiedorder(), "", WebchatUtil.mapToXml(reqData));
        
        // 返回结果解析
        Map<String, String> resp = WebchatUtil.processResponseXml(respXml);
        
        // 根据交易类型 解析返回前端所需的调用支付的参数
        Map<String, String> toclient = new HashMap<>();
        String prepayId = resp.get("prepay_id");
        
        // h5
        if(tradeType.equalsIgnoreCase("MWEB")){
			toclient.put("mwebUrl", resp.get("mweb_url")+"&redirect_url="+ URLEncoder.encode("WxRedirectUrl","utf-8"));
			toclient.put("tradeType", tradeType);
			toclient.put("prepayId", prepayId);
		}else{
			
			String timestamp = WebchatUtil.getTimeStamp();
			
			// 签名
			Map<String, String> finalpackage = new HashMap<>();
			finalpackage.put("appId", resp.get("appid"));
			finalpackage.put("timeStamp", timestamp);
			finalpackage.put("nonceStr", nonceStr);
			
			// 小程序
			if (tradeType.equalsIgnoreCase("JSAPI")){
				// 获取prepay_id后，拼接最后请求支付所需要的package
				finalpackage.put("package", "prepay_id=" + prepayId);
				finalpackage.put("signType", "MD5");
				
				// 签名
				String finalsign = WebchatUtil.generateSignature(finalpackage, wxaccount.getPartenerkey());
				toclient.put("package","prepay_id=" + prepayId);
				toclient.put("signType","MD5");
				toclient.put("paySign",finalsign);
			}else if(tradeType.equalsIgnoreCase("APP")){
				// App
                finalpackage.put("package", "Sign=WXPay");
                finalpackage.put("partnerid", resp.get("mch_id"));
                finalpackage.put("prepayid", prepayId);
                
                // 签名
                String finalsign = WebchatUtil.generateSignature(finalpackage, wxaccount.getPartenerkey());
                toclient.put("partnerId",resp.get("mch_id"));
                toclient.put("prepayId",prepayId);
                toclient.put("packageValue","Sign=WXPay");
                toclient.put("sign",finalsign);
			}
			
			// 返回前端
			toclient.put("appId", resp.get("appid"));
			toclient.put("timeStamp",timestamp);
			toclient.put("nonceStr",nonceStr);
		}
        return toclient;
	}

	@Override
	public Map<String, String> orderQuery() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Map<String, String> downloadBill() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Map<String, String> refundQuery() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

}
